using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Beaker.Injection;
using Microsoft.Practices.ServiceLocation;

namespace OpenCube.Nbt.Specs.Builders
{
	public sealed class QueryContainerStub
		: IQueryContainer
	{
		private readonly IDictionary<Type, object> _instances
			= new Dictionary<Type, object>();

		public QueryContainerStub()
		{
		}

		public QueryContainerStub Register<TService>(TService service)
		{
			_instances.Add(typeof(TService), service);
			return this;
		}

		public TService GetInstance<TService>()
			where TService : class
		{
			return (TService)GetInstance(typeof(TService));
		}

		public object GetInstance(Type serviceType)
		{
			object instance;
			if (_instances.TryGetValue(serviceType, out instance))
				return instance;

			TypeInfo info = serviceType.GetTypeInfo();
			if (!info.IsAbstract)
			{
				if (!info.IsAbstract && info.DeclaredConstructors.Any(c => c.GetParameters().Length == 0))
					return Activator.CreateInstance(serviceType);

				if (info.DeclaredConstructors.Count() == 1)
				{
					var constructor = info.DeclaredConstructors.Single();
					List<object> args = new List<object>();
					foreach (var parameter in constructor.GetParameters())
					{
						var arg = GetInstance(parameter.ParameterType);
						args.Add(arg);
					}
					return Activator.CreateInstance(serviceType, args.ToArray());
				}
			}

			throw new ActivationException();
		}

		public IEnumerable<TService> GetAllInstances<TService>()
		{
			throw new NotImplementedException();
		}

		public IEnumerable<object> GetAllInstances(Type serviceType)
		{
			throw new NotImplementedException();
		}
	}
}
